package com.ironone.mediaplayerdemo;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.AudioManager.OnAudioFocusChangeListener;

public class MyMediaPlayer {

	private static MediaPlayer mediaPlayer = null;
	private static String url_std = "http://198.50.207.172:8000/live.mp3";
	private static String url_hd = "http://198.50.207.172:8000/live.mp3";

	private static int iVolume;
	private final static int INT_VOLUME_MAX = 100;
	private final static int INT_VOLUME_MIN = 0;
	private final static float FLOAT_VOLUME_MAX = 1;
	private final static float FLOAT_VOLUME_MIN = 0;
	private final static int FADE_DURATION = 500; // In milliseconds. Can't be 0

	private static MediaPlayerStatus mediaPlayerStatus = MediaPlayerStatus.released;
	private static boolean isPlayerOnBackground = false;
	private static boolean hd = false;

	public static String SVC_NOTIFICATION = "com.ironone.SERVICE_CALLBACK";
	public static String ACT_NOTIFICATION = "com.ironone.ACTIVITY_CALLBACK";
	public static String VALUE = "value";

	private MyMediaPlayer(){
	}


	public static MediaPlayerStatus getMediaPlayerStatus(){
		return mediaPlayerStatus;
	}

	public static void setMediaPlayerStatus(MediaPlayerStatus status){
		mediaPlayerStatus = status;
	}

	public static boolean getIsPlayerOnBackground(){
		return isPlayerOnBackground;
	}

	public static void setIsPlayerOnBackground(boolean x){
		isPlayerOnBackground = x;
	}

	public static boolean getIsHDOn(){
		return hd;
	}

	public static void setIsHDOn(boolean y){
		hd = y;
	}


	public static MediaPlayer getMediaPlayerInstance(){
		if (mediaPlayer == null) {
			mediaPlayer = new MediaPlayer();
		}
		return mediaPlayer;
	}

	public static void prepareMediaPlayer(){
		try {
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

			if(getIsHDOn())
				mediaPlayer.setDataSource(url_hd);
			else
				mediaPlayer.setDataSource(url_std);

			mediaPlayer.prepareAsync();
		} catch (IllegalArgumentException e) {
			releaseMediaPlayer();
		} catch (IllegalStateException e) {
			releaseMediaPlayer();
		} catch (IOException e) {
			releaseMediaPlayer();
		} catch (Exception e) {
			releaseMediaPlayer();
		}
	}

	public static void playMediaPlayer(){
		incVolume(FADE_DURATION);
		mediaPlayer.start();
		mediaPlayerStatus = MediaPlayerStatus.playing;

		/*try {
			wifiLock.acquire();
		} catch (Exception e) {
			e.printStackTrace();
		}*/
	}

	public static void pauseMediaPlayer(){
		decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.paused);
		//mediaPlayerStatus = MediaPlayerStatus.paused;

		/*try {
			wifiLock.release();
		} catch (Exception e) {
			e.printStackTrace();
		}*/
	}

	public static void resetMediaPlayer(){
		if (mediaPlayer != null)
			decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.reseted);

		/*try {
			wifiLock.release();
		} catch (Exception e) {
			e.printStackTrace();
		}*/
	}

	public static void releaseMediaPlayer(){
		if (mediaPlayer != null) {
			decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.released);

			/*try {
				wifiLock.release();
			} catch (Exception e) {
				e.printStackTrace();
			}*/
		}
	}

	public static void resetAndPrepareMediaPlayer(){
		decVolumeAndProceed(FADE_DURATION, MediaPlayerStatus.resetAndPrepare);

		/*try {
			wifiLock.release();
		} catch (Exception e) {
			e.printStackTrace();
		}*/
	}

	public static void getMediaPlayerAudioFocus(final Context context){
		try {
			AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
			audioManager.requestAudioFocus(new OnAudioFocusChangeListener() {

				@Override
				public void onAudioFocusChange(int focusChange) {
					switch (focusChange) {
					case AudioManager.AUDIOFOCUS_GAIN:
						// Resume playback
						if(MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.released || 
						MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.reseted){
							MyMediaPlayer.prepareMediaPlayer();
						}else if (MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.paused){
							MyMediaPlayer.playMediaPlayer();
						}
						MyMediaPlayer.getMediaPlayerInstance().setVolume(1.0f, 1.0f);
						break;

					case AudioManager.AUDIOFOCUS_LOSS:
						// Lost focus for an unbounded amount of time: stop playback and release media player
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.playing){
							//MyMediaPlayer.releaseMediaPlayer();

							if (MyMediaPlayer.getIsPlayerOnBackground()){
								MyMediaPlayer.releaseMediaPlayer();
							}else {
								Intent intent3 = new Intent(SVC_NOTIFICATION);
								intent3.putExtra(VALUE, MyMediaPlayerServiceNotifyStatus.audioFocusLost.ordinal()); // value == 3
								context.sendBroadcast(intent3);
							}
						}
						break;

					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
						// Lost focus for a short time, but we have to stop
						// playback. We don't release the media player because playback
						// is likely to resume
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.playing)
							MyMediaPlayer.pauseMediaPlayer();
						break;

					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
						// Lost focus for a short time, but it's ok to keep playing
						// at an attenuated level
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.playing)
							MyMediaPlayer.getMediaPlayerInstance().setVolume(0.1f, 0.1f);
						break;
					}
				}
			}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	

	//Start increasing volume in increments
	private static void incVolume(int fadeDuration){
		if(fadeDuration == 0)
			fadeDuration = 1;

		//Set current volume, depending on fade or not
		if (fadeDuration > 0) 
			iVolume = INT_VOLUME_MIN;
		else 
			iVolume = INT_VOLUME_MAX;

		updateVolume(0);

		//Start increasing volume in increments
		if(fadeDuration > 0)
		{
			final Timer timer = new Timer(true);
			TimerTask timerTask = new TimerTask() 
			{
				@Override
				public void run() 
				{
					updateVolume(1);
					if (iVolume == INT_VOLUME_MAX)
					{
						timer.cancel();
						timer.purge();
					}
				}
			};

			// calculate delay, cannot be zero, set to 1 if zero
			int delay = fadeDuration/INT_VOLUME_MAX;
			if (delay == 0) delay = 1;
			timer.schedule(timerTask, delay, delay);
		}
	}

	private static void decVolumeAndProceed(int fadeDuration, final MediaPlayerStatus playerStatus){
		if(fadeDuration == 0)
			fadeDuration = 1;

		//Set current volume, depending on fade or not
		if (fadeDuration > 0) 
			iVolume = INT_VOLUME_MAX;
		else 
			iVolume = INT_VOLUME_MIN;

		updateVolume(0);

		//Start increasing volume in increments
		if(fadeDuration > 0)
		{
			final Timer timer = new Timer(true);
			TimerTask timerTask = new TimerTask()
			{
				@Override
				public void run()
				{   
					updateVolume(-1);
					if (iVolume == INT_VOLUME_MIN)
					{
						switch (playerStatus.ordinal()) {
						case 0: //MediaPlayerStatus.playing
							break;

						case 1: //MediaPlayerStatus.paused
							if (mediaPlayer.isPlaying()){ 
								mediaPlayer.pause();
								mediaPlayerStatus = MediaPlayerStatus.paused;
							}
							break;

						case 2: //MediaPlayerStatus.buffering
							break;

						case 3: //MediaPlayerStatus.released
							if(mediaPlayer.isPlaying()) {
								mediaPlayer.stop();				
							}
							mediaPlayer.release();
							mediaPlayer = null;
							mediaPlayerStatus = MediaPlayerStatus.released;

							break;

						case 4: //MediaPlayerStatus.reseted
							if(mediaPlayer.isPlaying()) {
								mediaPlayer.stop();				
							}
							mediaPlayer.reset();
							mediaPlayerStatus = MediaPlayerStatus.reseted;
							break;

						case 5: //MediaPlayerStatus.forcePaused
							break;

						case 6: //MediaPlayerStatus.resetAndPrepare
							if(mediaPlayer.isPlaying()) {
								mediaPlayer.stop();				
							}
							mediaPlayer.reset();
							mediaPlayerStatus = MediaPlayerStatus.reseted;
							prepareMediaPlayer();
							break;							

						default:
							break;
						}

						timer.cancel();
						timer.purge();
					}
				}
			};

			// calculate delay, cannot be zero, set to 1 if zero
			int delay = fadeDuration/INT_VOLUME_MAX;
			if (delay == 0) delay = 1;
			timer.schedule(timerTask, delay, delay);
		}           
	}

	private static void updateVolume(int change){
		//increment or decrement depending on type of fade
		iVolume = iVolume + change;

		//ensure iVolume within boundaries
		if (iVolume < INT_VOLUME_MIN)
			iVolume = INT_VOLUME_MIN;
		else if (iVolume > INT_VOLUME_MAX)
			iVolume = INT_VOLUME_MAX;

		//convert to float value
		float fVolume = 1 - ((float) Math.log(INT_VOLUME_MAX - iVolume) / (float) Math.log(INT_VOLUME_MAX));

		//ensure fVolume within boundaries
		if (fVolume < FLOAT_VOLUME_MIN)
			fVolume = FLOAT_VOLUME_MIN;
		else if (fVolume > FLOAT_VOLUME_MAX)
			fVolume = FLOAT_VOLUME_MAX;     

		mediaPlayer.setVolume(fVolume, fVolume);
	}


	
}
